// 教程地址：https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html

use std::io;
// 序曲部分 prelude：引入（Rust的）标准库 std （中的）输入输出库 io

use std::cmp::Ordering;
// 为了正确背诵书写这一句，给 vscode 安装了 rust-analyzer 插件:-)
// Ordering 是枚举型(enum type)，下面是在vs code 中查看其定义得到的：
// pub enum Ordering { Less = -1, Equal = 0, Greater = 1, }

use rand::Rng;
// Rng 定义了随机数生成器实现的方法，是一种 trait，
// 理解：第10章10.2节标题 Traits: Defining Shared Behavior

fn main() {
    println!("Guess the number!");
    // Rust里 println! 加感叹号叫做 宏 Macro
    // 理解：第19章19.5节讲解 Macros:
    // All of these macros expand to produce more code than the code you’ve written manually.
    // 宏 Macro 扩展出（expand to produce ）更多代码（比纯手写）

    let secret_number = rand::thread_rng().gen_range(1..=100);
    // thread_rng 随机数生成器中的一种，它使用当前执行线程
    // range expression 范围表达式用了 start..=end，闭区间型（inclusive）

    // println!("The secret number is : {secret_number}");

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();
        // Rust 中用 let 声明创建变量，默认是不可变的（immutable）
        // 我们希望 guess 是可变的，因此增加 mut 在 guess 变量前。
        // String 是 Rust 标准库提供的 string 类型，
        // String::new() 函数返回一个新的 String 实例。

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");
        // 上面"&"符号，表明 read_line()的参数是个引用（Reference）
        // 在Rust中，引用保证了较其他语言的优势：安全性（how safe）和易用性（how easy）
        // 引用方式，避免了成倍次地（multiple times）拷贝数据到内存中
        // 注意：写法是 &mut guess 而不是 mut &guess
        // &mut guess 写法时 Rust 认为[mut guess]整体为引用
        // mut &guess 写法时 Rust 认为[guess]是引用？
        // 实际上定义 guess 时是 mutable 变量，而 Reference 默认是 immutable 量。

        // 异常处理
        // read_line() 接受输入，返回 Result 枚举类型
        // 定义：enum Result<T, E> { Ok(T), Err(E), }
        // 特性：如果不写异常处理，编译可以通过，但会输出 warning
        // warning: unused `Result` that must be used

        let guess: u32 = guess.trim().parse()
            .expect("Need a N!U!M!B!E!R! input!");
        /*
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };*/
        /*
            match 在 Rust 叫 控制流结构 Control Flow Construct
            是 Construct 不是 C语言中的 struct
            C 语言使用 control statement
            Rust 认为 match 是 extremely powerful
            match 自动让你漏不掉所有的选项
        */
        println!("You guessed: {guess}");

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"), // 先比较后处理，叫一个 arm
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}
